package com.wing.actor;

import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wing.actor.mailbox.ActorMailbox;
import com.wing.actor.message.Message;

/**
 * Actor父类
 * @author 杜祥
 * @create 2017年9月11日
 */
public abstract class AbstractActor implements Actor
{
	private final static Logger log = LoggerFactory.getLogger(AbstractActor.class);
	
	/**
	 * 名称
	 */
	protected String name = "";
	
	
	/**
	 * 组名称
	 */
	protected String groupName = "";
	
	
	/**
	 * 状态
	 */
	protected ActorState state = ActorState.NONE;
	
	
	/**
	 * 是否激活
	 */
	protected volatile boolean active = false;
	
	
	
	/**
	 * 所属的调度器
	 */
	protected ActorWorkerDispatcher dispatcher;
	
	
	/**
	 * 是否已经在调度器中
	 */
	protected boolean inDispatcher = false;
	
	
	/**
	 * 锁
	 */
	protected ReentrantLock lock = new ReentrantLock();
	
	
	/**
	 * 邮箱
	 */
	protected ActorMailbox mailbox;
	
	
	
	AbstractActor(ActorMailbox mailbox)
	{
		this.mailbox = mailbox;
	}
	

	
	@Override
	public String getName()
	{
		return name;
	}
	
	
	
	@Override
	public void setName(String name)
	{
		this.name = name;
	}

	
	
	@Override
	public String getGroup()
	{
		return groupName;
	}

	
	@Override
	public void setGroup(String groupName)
	{
		this.groupName = groupName;
	}

	
	
	/**
	 * 获得Actor状态
	 * @return
	 */
	protected final ActorState getActorState()
	{
		return state;
	}



	final void setState(ActorState state)
	{
		this.state = state;
	}

	
	
	final ActorWorkerDispatcher getDispatcher()
	{
		return dispatcher;
	}



	/**
	 * 注册调度器
	 * @param dispatcher
	 */
	final void registerDispatcher(ActorWorkerDispatcher dispatcher) 
	{
		this.dispatcher = dispatcher;
		//设置为开始状态
		setState(ActorState.START);
		
		lock.lock();
		try 
		{
			dispatcherActor();
		}
		finally 
		{
			lock.unlock();
		}
	}
	
	
	/**
	 * 调度此Actor
	 */
	private final void dispatcherActor()
	{
		if(!inDispatcher) 
		{
			this.dispatcher.addActor(this);
			inDispatcher = true;
		}
	}
	
	
	
	
	
	/**
	 * 启动时的处理
	 */
	final void startup()
	{
		try
		{
			onStartup();
		}
		catch (Throwable e)
		{
			log.error("message startup error.", e);
		}
		finally 
		{
			//改变状态
			setState(ActorState.WORKER);
			
			//计算是否能循环执行
			lock.lock();
			try
			{
				if(hasMessage())
				{
					this.dispatcher.addActor(this);
				}
				else 
				{
					inDispatcher = false;
				}
			}
			finally
			{
				lock.unlock();
			}
		}
	}
	
	
	/**
	 * 启动时调用
	 */
	protected abstract void onStartup();
	
	
	
	
	
	/**
	 * 处理消息内容
	 */
	final void worker() 
	{
		try
		{
			Message message = pollMessage();
			
			if(message != null) 
			{
				receive(message);
			}
		}
		catch (Throwable e)
		{
			log.error("message worker error.", e);
		}
		finally 
		{
			lock.lock();
			try
			{
				if(hasMessage())
				{
					this.dispatcher.addActor(this);
				}
				else 
				{
					inDispatcher = false;
				}
			}
			finally
			{
				lock.unlock();
			}
		}
	}
	
	
	
	/**
	 * 接收消息
	 * @param messge				消息
	 */	
	protected abstract void receive(Message messge);

	
	
	
	
	/**
	 * 激活Actor时调用
	 */
	@Override
	public void activate()
	{
		
	}
	
	
	
	/**
	 * 停止Actor时调用
	 */
	@Override
	public void deactivate()
	{
		
	}
	
	
	
	/**
	 * 设置激活状态
	 * @param active
	 */
	void setActive(boolean active)
	{
		this.active = active;
	}

	


	/**
	 * 是否处于激活状态
	 */
	@Override
	public final boolean hasActive()
	{
		return active;
	}
	
	
	
	
	/**
	 * 获得第一个消息
	 * @return
	 */
	protected Message pollMessage()
	{
		lock.lock();
		try
		{
			return mailbox.poll();
		}
		finally
		{
			lock.unlock();
		}
	}
	


	
	/**
	 * 是否还有剩余消息
	 */
	@Override
	public boolean hasMessage()
	{
		return mailbox.size() > 0;
	}

	
	
	
	/**
	 * 消息的总数量
	 */
	@Override
	public int getMessageCount()
	{
		return mailbox.size();
	}



	/**
	 * 向此Actor发送消息
	 */
	@Override
	public boolean sendMessage(Message message)
	{
		if(!hasActive()) 
		{
			return false;
		}
		
		lock.lock();
		try 
		{
			mailbox.offer(message);
			
			dispatcherActor();
			
			return true;
		}
		finally 
		{
			lock.unlock();
		}
	}
	
	
	/**
	 * 清除信箱
	 */
	void clearMailbox() 
	{
		lock.lock();
		try
		{
			mailbox.clear();
		}
		finally
		{
			lock.unlock();
		}
	}
	
}
